package controllers

import javax.inject.Inject
import dao._
import play.api.libs.json.Json
import play.api.mvc._
import models.Tables._
import org.apache.commons.math3.stat.StatUtils
import tool.FormTool
import utils.Utils

import scala.concurrent.ExecutionContext.Implicits.global
import implicits.Implicits._

class GenomeBrowseController @Inject()(cc: ControllerComponents, bgAnnoDao: BgAnnoDao, bgCdsDao: BgCdsDao, bgPepDao: BgPepDao, fpkmDao: FpkmDao,
                                       mrnaDao: GeneDao) extends AbstractController(cc) {

  def toIndex = Action {
    Ok(views.html.genome.browse.index())
  }

  def getAllBgAnnos = Action.async { implicit request =>
    bgAnnoDao.selectAll.map { x =>
      val json = Utils.getJsonByTs(x)
      Ok(json)
    }
  }

  def detailInfoBefore = Action { implicit request =>
    val data = FormTool.geneIdForm.bindFromRequest().get
    Ok(views.html.genome.browse.detailInfo(data.geneId))
  }

  def getDetailInfo = Action.async { implicit request =>
    val data = FormTool.geneIdForm.bindFromRequest().get
    val geneId = data.geneId
    bgAnnoDao.selectByGeneId(geneId).map(_.get).zip(bgCdsDao.selectByGeneId(geneId).map(_.get)).
      zip(bgPepDao.selectByGeneId(geneId).map(_.get)).zip(mrnaDao.selectByGeneId(geneId)).
      map { case (((bgAnno, bgCds), bgPep), mrna) =>
        val json = bgAnno.myAsJson ++ bgCds.myAsJson ++ bgPep.myAsJson ++ mrna.myAsJson
        Ok(json)
      }
  }

  def boxPlotByGeneId = Action.async { implicit request =>
    val data=FormTool.geneIdForm.bindFromRequest().get
    val id=data.geneId
    val fpkms = fpkmDao.selectByGeneId(id)
    fpkms.map(x => Ok {
      val typeX = x.groupBy(_.group)
      val typeLong = typeX.map {
        case (kind, longs) =>
          val values = longs.map(_.value).toArray
          val minValue = values.min
          val Q1 = StatUtils.percentile(values, 25)
          val Q2 = StatUtils.percentile(values, 50)
          val Q3 = StatUtils.percentile(values, 75)
          val maxValue = values.max
          Array(kind, minValue.toString, Q1.toString, Q2.toString, Q3.toString, maxValue.toString)
      }
      val jsons = Json.obj("ev" -> typeLong.map(_.drop(1).map(_.toDouble)), "tissue" -> typeLong.map(_ (0)))
      Json.toJson(jsons)
    })
  }


}
